iT邦幫忙

2024 iThome 鐵人賽

DAY 22
0
JavaScript

用 TypeScript 重新定義前端開發:30 天的實踐與思考系列 第 22

Day22:使用 TypeScript 為 React 元件定義複雜的型別

  • 分享至 

  • xImage
  •  

在開發大型 React 應用程式時,製作一些抽象化元件能提升程式碼的可重用性和可維護性。而在 TypeScript 的幫助下,可以為這些元件加上嚴格的型別註記,確保元件在不同情況下的正確性。今天的文章將介紹如何利用 TypeScript,為高度抽象的 React 元件定義複雜型別。

一、什麼是高度抽象化的元件?

高度抽象化的元件指的是那些可以根據不同參數和配置來應對多種場景的元件。例如常見的表單輸入框元件(Input)可以被抽象化成能處理文字、數字、日期等不同型別輸入的元件。這種元件能大大減少重複程式碼,提升開發效率。

常見範例場景:通用的表單輸入元件

假設我們需要一個通用的輸入框元件,它可以接受不同型別的值(如 stringnumberboolean),並在輸入變化時觸發不同的行為。那麼如何定義元件的型別,以便確保根據不同輸入型別,輸出正確的結果,就是一項小挑戰。

二、定義複雜的型別

我們可以使用 TypeScript 的「泛型」和「條件型別」來實現這種靈活性。首先為元件定義一個泛型,該泛型會根據輸入的不同型別,動態決定 valueonChange 函式的型別。

定義型別

首先定義一個泛型 T,它表示輸入框接受的值的型別。無論是 stringnumber 還是其他型別,都可以通過這個泛型進行處理。

// 泛型 T 代表輸入的值的型別
type InputProps<T> = {
  label: string;
  value: T;
  onChange: (value: T) => void;
};

接下來,InputProps<T> 是一個型別,用來描述元件的 props,其中 valueonChange 的型別會根據泛型 T 動態變化。而 Input<T> 就是通用的輸入框元件,它根據不同的 T 來處理不同的值。

// 通用的 Input 元件,使用泛型來支持不同型別的值
function Input<T>({ label, value, onChange }: InputProps<T>) {
  return (
    <div>
      <label>{label}</label>
      <input
        value={String(value)} // 將 value 轉為字串顯示在輸入框中
        onChange={(e) => onChange(e.target.value as unknown as T)} // 將輸入的值轉為泛型 T
      />
    </div>
  );
}

三、範例應用:處理多種型別

現在,來介紹可以如何用這個 Input 元件來處理不同型別的輸入,如文字、數字和布林值吧!

1. 處理文字輸入

使用 Input<string> 來處理文字輸入,並確保 valueonChange 函數都具有正確的型別。

function TextInput() {
  const [text, setText] = React.useState<string>("");

  return (
    <Input
      label="Enter text"
      value={text}
      onChange={setText}
    />
  );
}

2. 處理數字輸入

使用了 Input<number>,一樣確保 value 是數字,且 onChange 函式能正確處理數字型別的變化。

function NumberInput() {
  const [number, setNumber] = React.useState<number>(0);

  return (
    <Input
      label="Enter number"
      value={number}
      onChange={setNumber}
    />
  );
}

3. 處理布林值輸入

function BooleanInput() {
  const [checked, setChecked] = React.useState<boolean>(false);

  return (
    <Input
      label="Toggle"
      value={checked}
      onChange={setChecked}
    />
  );
}

四、進一步抽象化

上述的簡單範例,已經展示了如何利用 TypeScript 的泛型來實現靈活的輸入元件,可以試想如何為更多複雜場景提供客製化的元件。

Input 元件根據屬性自動渲染

舉個例子,我們可以讓這個 Input 元件根據不同的 type 屬性(如 textnumbercheckbox)來自動渲染不同的輸入框型別。

// 根據 type 自動渲染輸入框
interface ExtendedInputProps<T> extends InputProps<T> {
  type: 'text' | 'number' | 'checkbox';
}

function ExtendedInput<T>({ label, value, onChange, type }: ExtendedInputProps<T>) {
  return (
    <div>
      <label>{label}</label>
      <input
        type={type}
        value={String(value)}
        onChange={(e) => onChange(e.target.value as unknown as T)}
      />
    </div>
  );
}

通過擴展的應用,就可以直接指定 type,而 ExtendedInput 會根據 type 自動選擇適當的輸入框型別。

五、結語

使用 TypeScript 為 React 元件定義複雜的型別,可以大大提高元件的靈活性與可靠性。泛型的使用也可以針對不同的需求進行高度抽象化,從而減少重複不必要的程式碼。在實際開發中,這種抽象化的方式可以廣泛應用在表單、按鈕組件等各種場景中,讓元件更加可重用、可擴展!


上一篇
Day21:使用 TypeScript 與 Redux,為 action 和 reducer 定義型別
下一篇
Day23:使用 TypeScript 為 API 請求和響應定義型別
系列文
用 TypeScript 重新定義前端開發:30 天的實踐與思考30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言